﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using Cow.Module;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

namespace Cow.Handler
{
    public class ImportExcelHandler : IImportHandler
    {
        public SharedStringTable SharedStringTableItem { get; set; }
        public Design Import(String filePath)
        {
            Design design = null;
            using (SpreadsheetDocument document = SpreadsheetDocument.Open(filePath, false))
            {
                design = new Design();
                WorkbookPart workbookPart = document.WorkbookPart;
                //获取所有Sheet信息
                IEnumerable<Sheet> sheetList = workbookPart.Workbook.Descendants<Sheet>();
                //取得共用字串表
                SharedStringTableItem = workbookPart.SharedStringTablePart.SharedStringTable;
                WorksheetPart worksheetPart = null;
                //获取类型
                Type type = typeof(Design);
                //获取属性信息
                PropertyInfo[] properties = type.GetProperties();
                for (int sheetIndex = 0; sheetIndex < sheetList.Count(); sheetIndex++)
                {                    
                    worksheetPart = (WorksheetPart)workbookPart.GetPartById(sheetList.ElementAt(sheetIndex).Id);
                    //获取对应当前sheet索引的属性
                    PropertyInfo propertie = properties.Where(item => IsMatchSheetProperty(sheetIndex, item)).FirstOrDefault();
                    if (propertie != null) 
                    {
                        if (sheetIndex == 0)
                        {
                            SetModuleName(worksheetPart.Worksheet, design);
                        }
                        dynamic list = propertie.GetValue(design, null);
                        SetData(worksheetPart.Worksheet, list);
                    }
                }
            }
            return design;
        }

        private void SetModuleName(Worksheet worksheet, Design design)
        {
            //获取所有行信息
            IEnumerable<Row> rowList = worksheet.Descendants<Row>();
            var moduleRow = rowList.Take(1).First();
            design.ModuleName = GetCellText(moduleRow.Descendants<Cell>().First()).Trim();
        }

        private void SetData<T>(Worksheet worksheet, Collection<T> dataInfo) where T : new()
        {
            //获取所有行信息
            IEnumerable<Row> rowList = worksheet.Descendants<Row>();
            //获取数据行
            var dataList = rowList.Skip(3);
            //获取类型
            Type type = typeof(T);
            //获取属性信息
            PropertyInfo[] properties = type.GetProperties();
            //循环数据行
            dataList.ToList().ForEach(row =>
            {
                int cellIndex = 0;
                T data = new T();
                foreach (Cell cell in row.Descendants<Cell>())
                {
                    //获取当前列的值
                    String value = GetCellText(cell) ?? String.Empty;
                    //如果第二列值为空，则认为当前sheet已经结束，跳出循环
                    if (cellIndex == 2 && String.IsNullOrEmpty(value))
                    {
                        return;
                    }
                    //获取对应当前列的属性
                    PropertyInfo propertie = properties.Where(item => IsMatchCellProperty(cellIndex, item)).FirstOrDefault();
                    if (propertie != null)
                    {
                        if (propertie.PropertyType == typeof(Boolean))
                        {
                            propertie.SetValue(data, value.Equals("√"), null);
                        }
                        else
                        {
                            propertie.SetValue(data, value, null);
                        }
                    }
                    cellIndex++;
                }
                dataInfo.Add(data);
            });
        }

        /// <summary>
        /// 是否和指定索引匹配的属性
        /// </summary>
        /// <param name="sheetIndex"></param>
        /// <param name="propertie"></param>
        /// <returns></returns>
        private bool IsMatchSheetProperty(int sheetIndex, PropertyInfo propertie)
        {
            bool isMatch = false;
            var attributes = propertie.GetCustomAttributes(typeof(SheetInfoAttribute), false);
            foreach (var attribute in attributes)
            {
                var sheetInfo = attribute as SheetInfoAttribute;
                if (sheetInfo.SheetIndex == sheetIndex)
                {
                    isMatch = true;
                    break;
                }
            }
            return isMatch;
        }

        /// <summary>
        /// 是否和指定索引匹配的属性
        /// </summary>
        /// <param name="cellIndex"></param>
        /// <param name="propertie"></param>
        /// <returns></returns>
        private bool IsMatchCellProperty(int cellIndex, PropertyInfo propertie)
        {
            bool isMatch = false;
            var attributes = propertie.GetCustomAttributes(typeof(CellInfoAttribute), false);
            foreach (var attribute in attributes)
            {
                var cellInfo = attribute as CellInfoAttribute;
                if (cellInfo.CellIndex == cellIndex)
                {
                    isMatch = true;
                    break;
                }
            }
            return isMatch;
        }

        /// <summary>
        /// 获取单元格的文本值
        /// </summary>
        /// <param name="cell"></param>
        /// <returns></returns>
        private string GetCellText(Cell cell)
        {
            if (cell.ChildElements.Count == 0)
            {
                return null;
            }
            string val = cell.CellValue.InnerText;
            if (cell.DataType != null && cell.DataType == CellValues.SharedString)
            {
                val = SharedStringTableItem.ChildElements[int.Parse(val)].InnerText;
            }
            return val;
        }
    }
}
